﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace IronWinter
{

    public class Map
    {

        public static int cellSize = 32; //32x32 pixel block
        //Pending class
        protected char[,] charTerrain; 
        protected bool[,] boolTerrain;
        protected List<Objectives> objectives;
        protected int[,] startingLocations; //Place player HQs at this location
        enum scenarios { TakeAndHold, DestroyHQ };
        protected List<Terrain> spriteTerrain;
        public int lvlWidth;
        public int lvlHeight;
        // BuildingTexture list order. [0] HQ, [1] Building, [2] Objective

        public int startingReq;

        public char[,] Terrain
        {
            get { return charTerrain; }
        }

        public List<Terrain> SpriteTerrain
        {
            get { return spriteTerrain; }
        }
        /*Terrain Text File
         * First line - integer representing Starting Requistion values for each player
         * Second line map begins;
         * 0 = Flat Land
         * H = HQ building (is 128x128) (
         * B = Building Position (64 x 64)
         * O = objective position (64 x 64)
         * X = (can not pass but no texture is created)
         * non-zero numbers will be Affiliated with Non-passable terrain, and apply the texture passed through the List in Initalize.
         * 0 for 1st element in the list, which should be the Background texture, Hence flat Land
         * 1 for 2st element in the list
         * 2 for the 3rd element in the list. ect/ect
         * As of yet the texture list is not standardized, but it Will be
         * 
         * Example
         * 2000xxxxxxxxxxxxxxxxx
         * 111111111111111111111
         * 1HXXX0000000000020O1
         * 1XXXX0000000000000001
         * 1XXXX0000222222220221
         * 1XXX200002O200HXXX001
         * 12200000000000xxxX021
         * 1O000000000000xxxX010
         * 111111111111111111111
         * 
         * Need to standardize Objective Size
         * Need to standardize HQ size
         * Each character will be represented as a "pixelBlockSize"x"PixelBlockSize" block
         * */
        public Map(string fileName)
        {
            startingReq = 0;
            charTerrain = readMap(fileName);

            lvlWidth = charTerrain.GetLength(1); // #Columns
            lvlHeight = charTerrain.GetLength(0); // #Rows

            boolTerrain = new bool[lvlHeight, lvlWidth];

            //game type
        }

        private char[ , ] readMap(string fileName)
        {
            string[] lines = System.IO.File.ReadAllLines("Content\\Maps\\" + fileName);

            startingReq = int.Parse(lines[0]);

            string temp = lines[1];
            temp = temp.Replace(" ", "");
            temp = temp.Replace("\t", "");
            int xLen = lines.Length;
            int yLen = temp.Length;
            
            char[,] charArray = new char[xLen, yLen];

            for(int i = 1; i < lines.Length; i++)
            {
                string s = lines[i];
                s = s.Replace(" ", String.Empty);
                s = s.Replace("\t", String.Empty);
                char[] lineArray = s.ToCharArray();
                for(int j = 0; j < lineArray.Length; j++)
                {
                    charArray[i,j] = lineArray[j];
                }
            }
            return charArray;
        }

        public void initalize()
        {
            // reqPlayers does nothing for now
            spriteTerrain = new List<Terrain>();
            objectives = new List<Objectives>();

            buildLevel();
            //Collision needs access to this but update methods won't accept it and it's never passed out for units to grab it.
            Collision.world = boolTerrain;
            //Don't be stingy :p
        }

        //Helper method for initalize. Reads the blocks and builds and object for it. 
        private void buildLevel()
        {
            foreach (Player p in Game1.players)
            {
                p.requisition = startingReq;
            }
            int HQCount = 1;

            // Build Map
            for (int i = 1; i < lvlHeight; i++)
            {
                for (int j = 0; j < lvlWidth; j++)
                {
                    int mvX = cellSize * i; // The translated X position on the drawn map
                    int mvY = cellSize * j; // the translated Y position on the Drawn map
                    boolTerrain[i, j] = true; //is passable
                    char c = charTerrain[i, j];

                    if (c == 'X')
                    {
                        boolTerrain[i, j] = false; //is not passable
                    }

                    // If
                    if (c == 'H')
                    {
                        foreach (Player p in Game1.players)
                        {
                            if (p.id == HQCount)
                            {
                                HQBuilding newHQ = (new HQBuilding(mvX, mvY, cellSize * 4, cellSize * 4,Game1.HQ, p));
                                spriteTerrain.Add(newHQ);
                                p.buildings.Add((Building)newHQ);
                                boolTerrain[i, j] = false; //is not passable
                                HQCount++;
                                break;
                            }
                        }
                        
                    }
                    else if (c == 'B')
                    {
                        spriteTerrain.Add(new Building(mvX, mvY, cellSize * 2, cellSize * 2, Game1.building, null));
                        boolTerrain[i, j] = false; //is not passable
                    }

                    else if (c == 'O')
                    {
                        Objectives newObjective = new Objectives(mvX, mvY, cellSize * 2, cellSize * 2, 25);
                        spriteTerrain.Add(newObjective);
                        objectives.Add(newObjective);
                        
                        boolTerrain[i, j] = false; //is not passable
                    }
                     
                    else if (c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9')
                    {
                        spriteTerrain.Add(new ImpassableTerrain(mvX, mvY, cellSize, cellSize, Game1.wall));
                        boolTerrain[i, j] = false; //is not passable
                    }
                    else
                    {
                        // curse
                    }

                }
                    

            }
        }

        //returns an integer value, 0 at default, a positive int when the game has ended signifying the winning player.  
        public int Update(GameTime gameTime)
        {
            //update objectives and players.
            foreach (Objectives o in objectives)
            {
                o.Update(gameTime);
            }

            //check for end game!
            //eventually

            return 0;
        }

        public void draw(SpriteBatch sb)
        {
            foreach(Terrain t in spriteTerrain)
            {
                t.Draw(sb);
            }

        }

    }
}
